home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvibook / libtex / pxlfont.c < prev    next >
C/C++ Source or Header  |  1994-03-18  |  7KB  |  305 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/lib/RCS/pxlfont.c,v 2.5 89/08/22 21:55:34 chris Exp $";
  10. #endif
  11.  
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <errno.h>
  16. #include "types.h"
  17. #include "error.h"
  18. #include "font.h"
  19. #include "fio.h"
  20.  
  21. /*
  22.  * PXL font operations.
  23.  */
  24. static int pxl_read(), pxl_getgly(), pxl_rasterise();
  25. static void pxl_freefont();
  26.  
  27. struct    fontops pxlops =
  28.     { "pxl", 0, 5.0, pxl_read, pxl_getgly, pxl_rasterise, pxl_freefont };
  29.  
  30. /*
  31.  * Local info.
  32.  */
  33. #define    PXLID    1001        /* ID denoting PXL files */
  34. #define    TAILSIZE (517 * 4)    /* size of pxl tail info */
  35.  
  36. /*
  37.  * pc describes one PXL character information block.
  38.  */
  39. struct pc {
  40.     i16    pc_width;    /* character width (pixels) */
  41.     i16    pc_height;    /* character height (pixels) */
  42.     i16    pc_xoffset;    /* X offset of reference point */
  43.     i16    pc_yoffset;    /* Y offset of reference point */
  44.     i32    pc_rastoff;    /* raster offset */
  45.     i32    pc_TFMwidth;    /* TFM width (FIXes) */
  46. };
  47.  
  48. /*
  49.  * pxl_details are the PXL-specific font details.
  50.  *
  51.  * We keep track of the number of characters converted to internal
  52.  * glyph form, and when all have been done, we discard the now-
  53.  * useless details.
  54.  */
  55. struct pxl_details {
  56.     int    pd_nconv;    /* number of characters converted */
  57.     char    *pd_ras;    /* raster space, until converted */
  58.     struct    pc pd_pc[128];    /* `font directory' */
  59. };
  60.  
  61. /*
  62.  * Get the pxl_details from font f.
  63.  */
  64. #define    ftopd(f) ((struct pxl_details *) (f)->f_details)
  65.  
  66. extern    errno;
  67. char    *malloc();
  68.  
  69. /*
  70.  * Read a PXL file.
  71.  */
  72. static int
  73. pxl_read(f, fd)
  74.     struct font *f;
  75.     int fd;
  76. {
  77.     register struct pxl_details *pd;
  78.     register FILE *fp;
  79.     register struct pc *pc;
  80.     register int i;
  81.     int saverr;
  82.     i32 pxlid;
  83.     struct stat st;
  84.  
  85.     fp = NULL;
  86.     if ((pd = (struct pxl_details *)malloc(sizeof (*pd))) == 0)
  87.         goto fail;
  88.     pd->pd_ras = 0;
  89.  
  90.     /*
  91.      * There should be 4n bytes, with an absolute minimum of TAILSIZE+4
  92.      * (+4 for the initial PXLID).
  93.      */
  94.     (void) fstat(fd, &st);
  95.     if ((st.st_size & 3) != 0 || st.st_size < (TAILSIZE + 4)) {
  96.         errno = EINVAL;
  97.         goto fail;
  98.     }
  99.  
  100.     /*
  101.      * Set up the raster pointer (if we need rasters).
  102.      */
  103.     if (f->f_flags & FF_RASTERS) {
  104.         i = st.st_size - (TAILSIZE + 4);
  105.         if (i != 0)  {
  106.             if ((pd->pd_ras = malloc((unsigned) i)) == 0)
  107.                 goto fail;
  108.             (void) lseek(fd, 4L, 0);
  109.             if (read(fd, pd->pd_ras, i) != i)
  110.                 goto fail;
  111.         }
  112.     }
  113.  
  114.     /*
  115.      * Read the glyph information.
  116.      */
  117.     errno = 0;        /* try to make errno meaningful */
  118.     if ((fp = fdopen(fd, "r")) == NULL) {
  119.         if (errno == 0)
  120.             errno = EMFILE;
  121.         goto fail;
  122.     }
  123.     (void) fseek(fp, (long) -TAILSIZE, 2);
  124.     for (i = 128, pc = pd->pd_pc; --i >= 0; pc++) {
  125.         fGetWord(fp, pc->pc_width);
  126.         fGetWord(fp, pc->pc_height);
  127.         fGetWord(fp, pc->pc_xoffset);
  128.         fGetWord(fp, pc->pc_yoffset);
  129.         fGetLong(fp, pc->pc_rastoff);
  130.         fGetLong(fp, pc->pc_TFMwidth);
  131.     }
  132.     f->f_checksum = GetLong(fp);
  133.     (void) GetLong(fp);        /* mag */
  134.     f->f_design_size = GetLong(fp);    /* designsize */
  135.     f->f_hppp = 0;            /* ??? maybe 200? */
  136.     f->f_vppp = 0;
  137.     (void) GetLong(fp);        /* dirpointer */
  138.     pxlid = GetLong(fp);
  139.     if (pxlid != PXLID)
  140.         error(0, 0, "Warning: strange PXL id (%d) in \"%s\"",
  141.             pxlid, f->f_path);
  142.  
  143.     f->f_details = (char *)pd;
  144.     if (FontHasGlyphs(f, 0, 128))
  145.         goto fail;
  146.     (void) fclose(fp);
  147.     pd->pd_nconv = 0;
  148.     return (0);
  149.  
  150. fail:
  151.     saverr = errno;
  152.     if (pd) {
  153.         if (pd->pd_ras)
  154.             free(pd->pd_ras);
  155.         free((char *)pd);
  156.     }
  157.     if (fp)
  158.         (void) fclose(fp);
  159.     else
  160.         (void) close(fd);
  161.     errno = saverr;
  162.     return (-1);
  163. }
  164.  
  165. /*
  166.  * Obtain the specified range of glyphs.
  167.  */
  168. static int
  169. pxl_getgly(f, l, h)
  170.     register struct font *f;
  171.     int l;
  172.     register int h;
  173. {
  174.     register struct glyph *g;
  175.     register struct pc *pc;
  176.     register int i;
  177.     struct pxl_details *pd;
  178.  
  179.     if ((pd = ftopd(f)) == NULL)
  180.         error(1, 0, "pxl_getgly details==0: cannot happen");
  181.     /*
  182.      * By definition, all 128 glyphs are valid.  Just copy the
  183.      * PXL information.
  184.      */
  185.     for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
  186.         g = f->f_gly[i];
  187.         g->g_flags = GF_VALID;
  188.         g->g_height = pc->pc_height;
  189.         g->g_width = pc->pc_width;
  190.         g->g_yorigin = pc->pc_yoffset;
  191.         g->g_xorigin = pc->pc_xoffset;
  192.         g->g_rawtfmwidth = pc->pc_TFMwidth;
  193.     }
  194.     return (0);
  195. }
  196.  
  197. /*
  198.  * Helper function for rasterise: return a pointer to a converted
  199.  * (malloc()ed and minimised) raster.
  200.  */
  201. static char *
  202. makeraster(h, w, rp)
  203.     register int h, w;
  204.     register char *rp;
  205. {
  206.     register char *cp;
  207.     register int i, o;
  208.     char *rv;
  209.  
  210.     /*
  211.      * The height and width values are in bits.  Convert width to
  212.      * bytes, rounding up.  The raw raster (at rp) is almost what
  213.      * we want, but not quite: it has `extra' bytes at the end of
  214.      * each row, to pad out to a multiple of four bytes.
  215.      */
  216.     w = (w + 7) >> 3;
  217.     o = (4 - w) & 3;    /* offset (number of `extra' bytes) */
  218.     if ((cp = malloc((unsigned) (h * w))) == NULL)
  219.         return (NULL);
  220.     if (o == 0) {
  221.         /*
  222.          * The raster fits exactly; just copy it to the allocated
  223.          * memory space.  (We must copy anyway, so that glyphs
  224.          * can be freed, e.g., after rotation.)
  225.          */
  226.         bcopy(rp, cp, h * w);
  227.         return (cp);
  228.     }
  229.     rv = cp;
  230.     while (--h >= 0) {
  231.         /*
  232.          * Copy each row, then skip over the extra stuff.
  233.          */
  234.         for (i = w; --i >= 0;)
  235.             *cp++ = *rp++;
  236.         rp += o;
  237.     }
  238.     return (rv);
  239. }
  240.  
  241. /*
  242.  * Obtain rasters for the specified glyphs.
  243.  */
  244. static int
  245. pxl_rasterise(f, l, h)
  246.     register struct font *f;
  247.     int l;
  248.     register int h;
  249. {
  250.     register struct glyph *g;
  251.     register struct pc *pc;
  252.     register int i;
  253.     register struct pxl_details *pd;
  254.  
  255.     if ((pd = ftopd(f)) == NULL)
  256.         error(1, 0, "pxl_rasterise details==0: cannot happen");
  257.     if (pd->pd_ras == NULL)
  258.         error(1, 0, "pxl_rasterise pd_ras==NULL: cannot happen");
  259.     for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
  260.         g = f->f_gly[i];
  261.         if (pc->pc_rastoff == 0) {
  262.             /*
  263.              * g should not claim a raster, since it has none.
  264.              */
  265.             if (HASRASTER(g))
  266.                 error(1, 0, "bad PXL glyph %d in \"%s\"",
  267.                     g->g_index, f->f_path);
  268.         } else {
  269.             g->g_raster = makeraster(pc->pc_height, pc->pc_width,
  270.                 pd->pd_ras + ((pc->pc_rastoff - 1) << 2));
  271.             if (g->g_raster == NULL)
  272.                 return (-1);    /* ??? */
  273.             g->g_rotation = ROT_NORM;
  274.         }
  275.     }
  276.  
  277.     /*
  278.      * If we have converted all the characters, dump the
  279.      * pre-conversion rasters.  In fact, dump everything.
  280.      */
  281.     pd->pd_nconv += h - l;
  282.     if (pd->pd_nconv == 128) {
  283.         free(pd->pd_ras);
  284.         free((char *)pd);
  285.         f->f_details = NULL;
  286.     }
  287.     return (0);
  288. }
  289.  
  290. /*
  291.  * Discard the font details.
  292.  */
  293. static void
  294. pxl_freefont(f)
  295.     struct font *f;
  296. {
  297.     struct pxl_details *pd;
  298.  
  299.     if ((pd = ftopd(f)) != NULL) {
  300.         if (pd->pd_ras != NULL)
  301.             free(pd->pd_ras);
  302.         free((char *)pd);
  303.     }
  304. }
  305.